import config from "./config";
import * as TextEncoding from "./TextEncoding";
const { sendKey , mKey } = config;
import Common from "./common.js";
export default class Server extends Common {
  UDP;
  userInfo;
  heartbeat;
  outsideQuery = new Map(); // 外部查询用户
  messageQueue = []; // 消息队列
  pendingMessages = new Map(); // 待确认的消息
  maxRetries = 3; // 最大重试次数
  retryTimeout = 1500; // 重试超时时间(ms)
  connectedClients = new Map(); // 已连接的客户端
  lastHeartbeats = new Map(); // 客户端最后心跳时间
  onLine = [];  // 在线
  offLine = []; // 离线
  killCountsMap = new Map(); // 狼人杀人总数总集合
  voteCountsMap = new Map(); // 投票的集合
  isServer = true;
  paddingMessageBack = new Map();  // 广播待确认消息
  paddingRetries = 0  // 待确认消息重试次数
  pollingSetTimeout = null; // 轮询定时器
  // 发送时间
  wolf_send_time = null
  witch_send_time = null
  guard_send_time = null
  prophet_send_time = null


  // 音频
  gameStartAudio = []  // 天黑了 请闭眼

  wolfStartAudio = [] // 狼人请睁眼
  wolfEndAudio = []   // 狼人请闭眼

  witchStartAudio = [] // 女巫请睁眼
  witchEndAudio = []   // 女巫请闭眼

  guardStartAudio = [] // 守卫请睁眼
  guardEndAudio = []   // 守卫请闭眼

  prophetStartAudio = [] // 预言家请睁眼
  prophetEndAudio = []   // 预言家请闭眼

  wolfAudioTime = []  // 狼人播放时长
  witchAudioTime = [] // 女巫播放时长
  guardAudioTime = [] // 守卫播放时长
  prophetAudioTime = [] // 预言家播放时长

  gameEndAudio = []  // 天亮了
  // 私有属性，用于存储实际数据


  /** 局内数据 音频 **/
  audioContext;
  currentAudioIndex = 0;
  preloadedAudioContexts = []; // 预加载的音频
  isPlayingAudio = false; // 是否正在播放音频
  audioPathsMap = new Map(); // 音频路径


  constructor(parameters) {
    super(parameters);
    this.create();
  }

  create() {
    this.UDP = wx.createUDPSocket();
    this.UDP.bind(config.servePort);
    this.onMessage();
    this.startHeartbeatCheck();
    this.userInfo = wx.getStorageSync("userInfo");
  }

  // 心跳检测
  startHeartbeatCheck() {
    clearInterval(this.heartbeat);
    this.heartbeat = null;
    this.heartbeat = setInterval(() => {
      if (this.UDP && this.heartbeat && this.lastHeartbeats.size) {
        const now = Date.now();
        this.onLine = []
        this.offLine = []
        const messageId = this.generateMessageId();
        this.onceSend({}); // 改为广播-----心跳
        console.log("心跳检测", now);
        this.lastHeartbeats.forEach((lastBeat, clientIP) => {
          // this.onceSend({},clientIP); // 改为广播-----心跳
          const { element } = this.getAssignPart(clientIP)
          if (now - lastBeat > 6000) {
             if(element.isLine) this.offLine.push(clientIP)
            // 4秒无心跳视为断线
            this.setPartOffLine(clientIP);
          } else {
            if(!element.isLine) this.onLine.push(clientIP)
            // 离线改在线
            this.setPartOnLine(clientIP);
          }
        });
        // 心跳设置在线离线
        if(this.offLine.length || this.onLine.length){
          if(this.offLine.length){
            this.offLine.forEach(ip => {
              this.lastHeartbeats.delete(ip)
            })
          }
          this.broadcastMessage({
            [mKey.messageType]: sendKey.setLine,
            ...(this.offLine ? {[mKey.offLine]:this.offLine} : {}),
            ...(this.onLine ? {[mKey.onLine]:this.onLine} : {}),
            [mKey.version] : this.computedVersion()
          });
        }
      }
    }, 2000);
  }
  
  // 发送在线离线消息
  sendLine(onLine = 0,offLine = 0) {
    // 设置清除人员心跳
    if(offLine){
      this.lastHeartbeats.delete(offLine)
    }
    // 操作设置 在线离线
    if(onLine || offLine){
      this.broadcastMessage({
        [mKey.messageType]: sendKey.setLine,
        ...(offLine ? {[mKey.offLine]:[offLine]} : {}),
        ...(onLine ? {[mKey.onLine]:[onLine]} : {}),
        [mKey.version] : this.computedVersion()
      });
    }
  }
  // 更新房间信息--- 广播
  broadcastMessage(message = {}) {
    this.paddingMessageBack.clear();
    
    const params = {
      [mKey.messageId]: this.generateMessageId(),
      [mKey.isNeedReply]: 1,
      ...message,
    };
    // 加入待发送队列
    this.gameMessage.players.forEach((item) => {
      if (item.ip && item.ip !== this.gameMessage.gameIp) {
        // 添加到待确认队列
        this.paddingMessageBack.set(item.ip,params)
      }
    });
    // 改为广播-----
    this.onceSend(params); 
    // 发给法官
    // if(this.gameMessage.participateIn){
      this.commonOnMessage(params);
    // }
    this.paddingRetries = 0
    // 队列检测
    this.pollingSendMessage(message[mKey.destroy] ? 1 : 0)
  }

  // 只发1次
  onceSend(message = {},address = config.broadcast,port = config.clientPort) {
    this._sendMessage(message, address, port);
  }

  // 发送消息（会尝试重发）
  send(message = {}, address = config.broadcast, port = config.clientPort) {
    const messageId = this.generateMessageId();
    const wrappedMessage = {
      [mKey.isNeedReply]: 1,
      ...message,
      [mKey.messageId]: messageId,
    };
    // 添加到待确认队列
    this.pendingMessages.set(messageId, {
      message: wrappedMessage,
      address,
      port,
      retries: 0,
    });
    this._sendMessage(wrappedMessage, address, port);
    this._startMessageRetry(messageId);
  }

  // 实际发送消息
  _sendMessage(message = {},address = config.broadcast,port = config.clientPort) {
    // loading处理
    if(message[mKey.loadingText]){
      if(this.loadingText){
        if(this.loadingText !== message[mKey.loadingText]){
          wx.hideLoading();
          wx.showLoading({
            title: message[mKey.loadingText],
            mask: true,
          });
        }
      } else {
        this.loadingText = message[mKey.loadingText];
        wx.showLoading({
          title: message[mKey.loadingText],
          mask: true,
        });
      }
    }
    const wrappedMessage = {
      ...message,
    }
    Object.keys(wrappedMessage).forEach((key) => {
      if (!wrappedMessage[key] && wrappedMessage[key] !== 0) {
        delete wrappedMessage[key];
      }
    });
    delete wrappedMessage[mKey.loadingText];
    this.UDP && this.UDP.send({
      address,
      message: JSON.stringify(wrappedMessage),
      port,
    });
  }
  
  // 轮询发送消息广播后（待确认的）
  pollingSendMessage(destroy) {
    clearTimeout(this.pollingSetTimeout);
    this.pollingSetTimeout = null;
    this.pollingSetTimeout = setTimeout(() => {
      if(!this.pollingSetTimeout) return;
      if(this.paddingMessageBack.size){
        if(this.paddingRetries < 3){
          this.paddingRetries++
          this.paddingMessageBack.forEach((value,ip) => {
            const { element } = this.getAssignPart(ip)
            if(element && element.isLine) this.onceSend(value,ip)
          });
          this.pollingSendMessage(destroy)
        }else{
          this.paddingRetries = 0
          this.paddingMessageBack.clear();
          wx.hideLoading();
          if(destroy){
                console.log('onHide555555===========')

            this.destroy()
          }
        }
      }else{
        this.paddingRetries = 0
        if(destroy){
           console.log('onHide666666===========')
          this.destroy()
        }
      }
    }, 2000);
  }

  // 启动消息重试机制
  _startMessageRetry(messageId) {
    setTimeout(() => {
      const pending = this.pendingMessages.get(messageId);
      if (pending) {
        if (pending.retries < this.maxRetries) {
          pending.retries++;
          this.pendingMessages.set(messageId, pending);
          this._sendMessage(pending.message, pending.address, pending.port);
          this._startMessageRetry(messageId);
        } else {
          this.pendingMessages.delete(messageId);
          if (pending.message[mKey.loadingText]) {
            wx.hideLoading();
            this.loadingText = undefined;
            wx.showToast({ 
              title: pending.message[mKey.loadingText] + "失败",
              icon: "none",
            });
          }
        }
      }
    }, this.retryTimeout);
  }

  // 接收数据方法
  onMessage() {
    this.UDP.onMessage((e) => {
      const decoder = new TextEncoding.TextDecoder("utf-8");
      const message = JSON.parse(decoder.decode(new Uint8Array(e.message)));
      const clientIP = e.remoteInfo.address;
      const clientPort = e.remoteInfo.port;
      // 同网络下其他房间消息
      if(clientPort === config.servePort) return;

      // 不是刚加入并且  没有这个IP 消息就返回
      const { element } = this.getAssignPart(clientIP)
      const type = [sendKey.client_get_game, sendKey.client_join_game]
      if (!type.includes(message[mKey.messageType]) && !element) return;

      // 处理需要回复的消息（立即回复）叫他赶紧清掉 持续发送
      if (message[mKey.isNeedReply] === 1) {
          this.onceSend({
            [mKey.backMessageType]: message[mKey.messageType],
            [mKey.backMessageTryId]: message[mKey.messageId],
          },
          clientIP
        );
      }

      // 清除消息C端发送等待重试的消息
      if (message[mKey.backMessageTryId]) {
        const pendingMessages = this.pendingMessages.get(message[mKey.backMessageTryId]);
        if(pendingMessages && pendingMessages.message[mKey.loadingText]){
           wx.hideLoading();
           this.loadingText === pendingMessages.message[mKey.loadingText] && (this.loadingText = undefined);
        }
        this.pendingMessages.delete(message[mKey.backMessageTryId]);
        //-------------------- 广播消除-----------------------
        const paddingMessageBack = this.paddingMessageBack.get(clientIP);
        const isOk = paddingMessageBack &&
                     paddingMessageBack[mKey.messageType] &&
                     message[mKey.backMessageType] &&
                     paddingMessageBack[mKey.messageType] === message[mKey.backMessageType]
        if(isOk){
          // 删除待发送数据
          this.paddingMessageBack.delete(clientIP);
        }
      }

      // 更新房间内的心跳时间
      if(this.lastHeartbeats.get(clientIP)){
        this.lastHeartbeats.set(clientIP, Date.now());
      }

      // 处理重复消息
      if (this._isDuplicateMessage(message)) {
        return;
      }

      if(Object.keys(message).length){
        console.log("============接收数据================",message)
      }
      
      // 玩家切出离开(离线)
      if (message[mKey.messageType] === sendKey.client_leave_room) {
        this.setPartOffLine(clientIP);
        this.sendLine(0,clientIP)
      }

      // 客户端找房间 ---- 发送客户端游戏信息
      if (message[mKey.messageType] === sendKey.client_get_game) {
        this.outsideQuery.set(clientIP, clientIP);
        const { count, userCount } = this.computedCount()
        this.send({
          [mKey.messageType]: sendKey.client_get_game,
          [mKey.count]: count,
          [mKey.userCount]: userCount,
          [mKey.roomId]: this.gameMessage.roomId,
          ...(this.gameMessage.players.find((d) => d.ip === clientIP) ? { [mKey.presence]: 1 } : {}),
        },clientIP,config.searchPort);
        return;
      }

      // 客户端想要返回
      if (message[mKey.messageType] === sendKey.client_back_join) {
          // 告诉他返回成功了
          this.setPartOnLine(clientIP);
          this.send({
              [mKey.messageType]: sendKey.client_back_join_ok,
              [mKey.userIp]: clientIP,
              [mKey.gameMessage]: this.gameMessage,
              [mKey.backMessageTryId]: message[mKey.messageId],
            },clientIP);
          //心跳
          this.lastHeartbeats.set(clientIP, Date.now());
          // 通知各位 有人回来了
          this.sendLine(clientIP,0)
          return
      }

      // 客户返回成功（返回）
      if(message[mKey.backMessageType] === sendKey.client_back_join_ok){
        this.syncGameData(clientIP)
      }

      // 客户端想要加入游戏
      if (message[mKey.messageType] === sendKey.client_join_game) {
        const players = this.gameMessage.players;
        // 设置房间ip
        this.gameMessage.gameIp = message[mKey.gameIp];
        if (this.gameMessage.participateIn) {
          players[0].ip = message[mKey.gameIp];
          this.ownGameMessage = players[0];
        }
        // 添加玩家
        for (let element of players) {
          if (!element.ip) {
            element.isLine = true;
            element.userPicture = message[mKey.userPicture];
            element.userName = message[mKey.userName];
            element.ip = clientIP;
            break;
          }
        }
        this.gameMessage.players = players;
        this.gameMessage = this.gameMessage;
        // 告诉他加入成功了
        this.send({
            [mKey.messageType]: sendKey.client_join_game_ok,
            [mKey.userIp]: clientIP,
            [mKey.gameMessage]: this.gameMessage,
            [mKey.backMessageTryId]: message[mKey.messageId],
          },
          clientIP
        );
      }

      // 加入成功（返回）
      if(message[mKey.backMessageType] === sendKey.client_join_game_ok){
        const version = this.computedVersion()
        this.lastHeartbeats.set(clientIP, Date.now());
        const { element } = this.getAssignPart(clientIP)
        // 告诉其他人有新人来了
        this.broadcastMessage({
          [mKey.messageType]: sendKey.playerAdd,
          [mKey.userName]: element.userName,
          [mKey.userPicture]: element.userPicture,
          [mKey.userIp]: clientIP,
          [mKey.version] : version
        });
        // 告诉叫门的  数量变化
        this.outsideQuery.delete(clientIP);
        const { count, userCount } = this.computedCount()
        this.onceSend({
            [mKey.messageType]: sendKey.client_get_game,
            [mKey.count]: count,
            [mKey.userCount]: userCount,
            [mKey.roomId]: this.gameMessage.roomId,
        },config.broadcast,config.searchPort);
        // 同步一下 是否有操作
        this.syncGameData(clientIP)
      }

      // 客户端尝试 保持连接
      if (message[mKey.messageType] === sendKey.keep_connect) {
        const players = this.gameMessage.players;
        const playerIndex = players.findIndex(
          (d) => d.ip === clientIP
        );
        if (playerIndex !== -1) {
          players[playerIndex].isLine = true;
          players[playerIndex].ip = clientIP;
        }
        this.gameMessage.players = players;
        this.gameMessage = this.gameMessage

        // 同步数据
        this.send({
          [mKey.messageType]: sendKey.keep_connect_ok,
          [mKey.gameMessage]: this.gameMessage,
          [mKey.userIp]: clientIP,
          [mKey.backMessageTryId]: message[mKey.messageId],
        },clientIP)
        // 告诉其他玩家 上线
        this.sendLine(clientIP,0)
      }

      // 保持连接后（返回）
      if(message[mKey.backMessageType] === sendKey.keep_connect_ok){
        //心跳
        this.lastHeartbeats.set(clientIP, Date.now());
        this.syncGameData(clientIP)
      }

      // 玩家主动退出当前游戏
      if (message[mKey.messageType] === sendKey.client_exit_room) {
        this.lastHeartbeats.delete(clientIP);
        // 更新数据--同步有人退出
        this.broadcastMessage({
          [mKey.messageType]: sendKey.exit,
          [mKey.userIp]: clientIP,
          [mKey.version] : this.computedVersion(),
        });
        // 告诉门外
        const { count, userCount } = this.computedCount()
        this.onceSend({
          [mKey.messageType]: sendKey.client_get_game,
          [mKey.count]: count,
          [mKey.userCount]: userCount,
          [mKey.roomId]: this.gameMessage.roomId,
        },config.broadcast,config.searchPort);
        return;
      }

      // 玩家更新用户的信息
      if (message[mKey.messageType] === sendKey.updata_user_info) {
        this.broadcastMessage({
          [mKey.messageType]: sendKey.updataUser,
          [mKey.userName]: message[mKey.userName],
          [mKey.userPicture]: message[mKey.userPicture],
          [mKey.userIp]: clientIP,
          [mKey.version]: this.computedVersion(),
        });
        return;
      }

      // 狼人杀人
      if (message[mKey.messageType] === sendKey.wolf_kill) {
        const killCountsMap = this.killCountsMap.get(message[mKey.userIp]);
        if (killCountsMap) {
          killCountsMap.num++;
          this.killCountsMap.set(message[mKey.userIp], killCountsMap);
        } else {
          this.killCountsMap.set(message[mKey.userIp], { num: 1 });
        }
        this.setPartOperated(clientIP,2)
      }

      // 女巫杀人
      if (message[mKey.messageType] === sendKey.witch_kill) {
        this.gameMessage.witchKill = false;
        this.gameMessage.WIKU = message[mKey.userIp]; // 毒药的杀人
        this.gameMessage = this.gameMessage
        this.setPartOperated(clientIP,2)
      }

      // 女巫救人
      if (message[mKey.messageType] === sendKey.witch_save) {
        this.gameMessage.witchSave = false;
        this.gameMessage.WISU = message[mKey.userIp]; // 守卫保护的
        this.gameMessage = this.gameMessage
        this.setPartOperated(clientIP,2)
      }

      // 守卫保护的人
      if (message[mKey.messageType] === sendKey.guard_kill) {
        this.gameMessage.GKU = message[mKey.userIp];
        this.gameMessage = this.gameMessage
        this.setPartOperated(clientIP,2)
      }

      // 预言家查看的人
      if (message[mKey.messageType] === sendKey.prophet_kill) {
        this.gameMessage.PKU = message[mKey.userIp];
        this.gameMessage = this.gameMessage
        this.setPartOperated(clientIP,2)
      }

      // 猎人带走的人
      if (message[mKey.messageType] === sendKey.hunter_kill) {
        this.gameMessage.HKU = message[mKey.userIp];
        this.gameMessage = this.gameMessage
        this.setPartOperated(clientIP,2)
        // 结算
        this.hunterSettlement();
      }

      // 放弃
      if (message[mKey.messageType] === sendKey.giveUp_go) {
        console.log("放弃===");
        this.setPartOperated(clientIP,3)
        // 所有人操作完就去结算
        // this.allOperatedOk() &&  this.voteSettlement();
      }

      // 猎人放弃
      if (message[mKey.messageType] === sendKey.giveUp_go_hunter) {
        this.setPartOperated(clientIP,3)
        // 猎人放弃后结算
        this.hunterGiveUpSettlement();
      }

      // 投票
      if (message[mKey.messageType] === sendKey.vote_kill) {
        const { element } = this.getAssignPart(message[mKey.userIp]);
        this.setPartOperated(clientIP,2)
        if (element) {
          const voteCountsMap = this.voteCountsMap.get(element.ip);
          if (voteCountsMap) {
            voteCountsMap.num = voteCountsMap.num + 1;
            this.voteCountsMap.set(element.ip, voteCountsMap);
          } else {
            this.voteCountsMap.set(element.ip, { ...element, num: 1 });
          }

          const gameVoteCollect = this.gameMessage.gameVoteCollect
          const gameVoteList = Object.keys(gameVoteCollect) || []
          const isExist = gameVoteList.includes(element.ip)
          if(isExist){
            if(!gameVoteCollect[element.ip].includes(clientIP)){
              gameVoteCollect[element.ip].push(clientIP)
            }
          }else{
            gameVoteCollect[element.ip] = [clientIP]
          }
          this.gameMessage.gameVoteCollect = gameVoteCollect
          this.gameMessage = this.gameMessage
        }
        // 所有人操作完就去结算
        // this.allOperatedOk() &&  this.voteSettlement();
      }
    });
  }

  // 创建房间
  createGame(confirm, list) {
    if (confirm && +confirm) {
      // 参与把自己加进去
      list[0]["userName"] = this.userInfo.userName;
      list[0]["userPicture"] = this.userInfo.userPicture;
      list[0]["ip"] = this.gameMessage.gameIp;
      this.gameMessage.participateIn = true;
    }
    this.gameMessage.players = list;
    this.gameMessage.roomId = new Date().getTime().toString().slice(3, 9);
    this.gameMessage = this.gameMessage
    if(confirm && +confirm){
    this.ownGameMessage = JSON.parse(JSON.stringify(this.gameMessage.players[0]))
    }
    const { count, userCount } = this.computedCount()
    this.onceSend({
      [mKey.messageType]: sendKey.client_get_game,
      [mKey.count]: count,
      [mKey.userCount]: userCount,
      [mKey.roomId]: this.gameMessage.roomId,
    });
    // 同步角色和数量
    this.setRoleAndCount()
    // 角色以及音频准备
    this.characterAudioPreparation();
  }

  // 暂时离开房间
  beRightBack(){
    this.broadcastMessage({ 
      [mKey.messageType]: sendKey.right_back,
      [mKey.destroy]: 1
    });
    this.clearAudios();
    // 存起来--游戏数据
    this.gameMessage.gameOutTime = Date.now();
    this.gameMessage = this.gameMessage
    wx.setStorageSync("gameMessage", this.gameMessage);
  }

  // 房主离开后返回房间
  startBackGame(){
    // 提示继续游戏 还是取消关闭房间
    this.pageContext.setData({ modalCole: 42 })
  }
  
  // 房主离开后返回房间
  continueGame(){
    // 返回同步心跳
    this.gameMessage.players.forEach((element) =>{
      if(element.ip && element.ip !== this.ownGameMessage.ip){
        this.lastHeartbeats.set(element.ip, Date.now());
      }
    })
    // 告诉各位又回来了
    this.broadcastMessage({
      [mKey.messageType]: sendKey.client_back_game,
      [mKey.gameMessage]: this.gameMessage
    });
    
    this.pageContext.setData({ modalCole: 0 })
    // 同步角色和数量
    this.setRoleAndCount()
    // 角色以及音频准备
    this.characterAudioPreparation();
    // 判断是否是播放中 中断
    console.log('continueGame===========')
    if(this.gameMessage.gameState === 0){
      this.currentAudioIndex = 0
      this.playNextAudio();
    }
    if(this.gameMessage.gameState === 1){
      const isWKU = !this.gameMessage.WKU;
      const isOperated = this.gameMessage.players.find(element => element.code === 7 && element.operated === 1);
      console.log(this.gameMessage.players,'======this.gameMessage.players=====')
      console.log('isWKU===========',isWKU,isOperated)
      if(isWKU && isOperated){
        // 播放音频
        const index = this.preloadedAudioContexts.findIndex(d => d.type === 1);
        this.currentAudioIndex = index - 2
        this.playNextAudio();
      }else{
        const index = this.preloadedAudioContexts.findIndex(d => d.type === 10);
        this.currentAudioIndex = index + 1
        this.playNextAudio();
      }
    }
    if(this.gameMessage.gameState === 2){
      const { WISU, WIKU, witchSave, witchKill } = this.gameMessage;
      const isWI = !WIKU && !WISU && (witchSave || witchKill) // 是否有毒药;
      const isOperated = this.gameMessage.players.find(element => element.code === 5 && element.operated === 1);
      if(isWI && isOperated){
        // 播放音频
        const index = this.preloadedAudioContexts.findIndex(d => d.type === 2);
        this.currentAudioIndex = index - 2
        this.playNextAudio();
      }else{
        const index = this.preloadedAudioContexts.findIndex(d => d.type === 20);
        if(this.preloadedAudioContexts.length - index > 6){
          this.currentAudioIndex = index + 1
          this.playNextAudio();
        }
      }
    }
    if(this.gameMessage.gameState === 3){
      const GKU = !this.gameMessage.GKU
      const isOperated = this.gameMessage.players.find(element => element.code === 3 && element.operated === 1);
      if(GKU && isOperated){
        // 播放音频
        const index = this.preloadedAudioContexts.findIndex(d => d.type === 3);
        this.currentAudioIndex = index - 2
        this.playNextAudio();
      }else{
        const index = this.preloadedAudioContexts.findIndex(d => d.type === 30);
        if(this.preloadedAudioContexts.length - index > 6){
          this.currentAudioIndex = index + 1
          this.playNextAudio();
        }
      }
    }
    if(this.gameMessage.gameState === 4){
      const PKU = !this.gameMessage.PKU
      const isOperated = this.gameMessage.players.find(element => element.code === 4 && element.operated === 1);
      if(PKU && isOperated){
        // 播放音频
        const index = this.preloadedAudioContexts.findIndex(d => d.type === 4);
        this.currentAudioIndex = index - 2
        this.playNextAudio();
      }else{
        const index = this.preloadedAudioContexts.findIndex(d => d.type === 40);
        if(this.preloadedAudioContexts.length - index > 6){
          this.currentAudioIndex = index + 1
          this.playNextAudio();
        }
      }
    }
    if(this.gameMessage.gameState === 105 || this.gameMessage.gameState === 106){
      this.gameMessage.players.forEach((element) => {
        if(element.isLive && !element.out && element.operated === 1){
          // 同步一下 是否有操作
          this.syncGameData(element.ip)
        }
      })
    }
  }

  // 解散房间（确认后）
  closeGame() {
    this.broadcastMessage({ [mKey.messageType]: sendKey.close_game })
    // 告诉叫门的
    this.onceSend({ [mKey.messageType]: sendKey.close_game }, config.broadcast, config.searchPort)
    wx.showLoading({ title: "解散中", mask: true });
    setTimeout(() => {
      wx.hideLoading();
      this.destroy();
      const pages = getCurrentPages();
      const routeStackLength = pages.length;
      routeStackLength > 1 ? wx.navigateBack({ delta: 2}) : wx.redirectTo({ url: '/pages/home/home' })
    }, 2000);
  }
  // 退出房间(直接退出)
  closeGameDirect() {
    this.broadcastMessage({ [mKey.messageType]: sendKey.close_game })
    // 告诉叫门的
    this.onceSend({ [mKey.messageType]: sendKey.close_game }, config.broadcast, config.searchPort)
    wx.hideLoading();
    this.destroy();
  }
  // 重置房间数据
  resetGameNet() {
    const gameMessage = this.gameMessage;
    const players = JSON.parse(JSON.stringify(gameMessage.players));
    players.forEach( element => {
      // 房主 也参加游戏需要更换ip
      if(element.ip !== this.gameMessage.gameIp){
          element.votes = [];
          element.isLive = true;
          element.isLine = true;
          element.ip = '';
          element.userName = '';
          element.userPicture = '';
          element.operated = 0;
      }
    })
    gameMessage.players = players
    this.gameMessage = gameMessage
    this.pageContext.setData({ modalCole: 0 })
  }
  // 网络变化退出房间
  exitGameNet() {
    this.destroy();
    const pages = getCurrentPages();
    const routeStackLength = pages.length;
    routeStackLength > 1 ? wx.navigateBack({ delta: 2}) : wx.redirectTo({ url: '/pages/home/home' })
  }
  
  // 同步功能
  syncGameData(ip) {
    const { element } = this.getAssignPart(ip);
    if(this.gameMessage.gameState === 1 && element.code === 7 && element.isLive && element.operated === 1){
      // 发送狼技能
      this.send({
        [mKey.messageType]: sendKey.wolf_permit,
        [mKey.progressTime]: this.gameMessage.wolf_time,
        [mKey.sendTime]: this.wolf_send_time || Date.now()
      },ip);
    }
    if(this.gameMessage.gameState === 2 && element.code === 5 && element.isLive && element.operated === 1){
      // 发送女巫技能
      this.send({
        [mKey.messageType]: sendKey.witch_permit,
        [mKey.WKU]: this.gameMessage.WKU,
        [mKey.witchKill]: this.gameMessage.witchKill, 
        [mKey.witchSave]: this.gameMessage.witchSave,
        [mKey.progressTime]: this.gameMessage.witch_time,
        [mKey.sendTime]: this.witch_send_time || Date.now()
      },ip);
    }
    if(this.gameMessage.gameState === 3 && element.code === 4 && element.isLive && element.operated === 1){
      // 发送预言家技能
      this.send({
        [mKey.messageType]: sendKey.prophet_permit,
        [mKey.progressTime]: this.gameMessage.prophet_time,
        [mKey.sendTime]: this.prophet_send_time || Date.now()
      },ip);
    }
    if(this.gameMessage.gameState === 3 && element.code === 3 && element.isLive && element.operated === 1){
      // 发送守卫技能
      this.send({
        [mKey.messageType]: sendKey.guard_permit,
        [mKey.progressTime]: this.gameMessage.guard_time,
        [mKey.sendTime]: this.guard_send_time || Date.now()
      },ip);
    }
    if(this.gameMessage.gameState === 5 && element.code === 2 && element.isLive && element.operated === 1){
      // 发送猎人技能
      this.send({
        [mKey.messageType]: sendKey.hunter_permit,
        [mKey.knockOut]: this.gameMessage.knockOut,
        [mKey.gameVoteCollect]: this.gameMessage.gameVoteCollect, // 投票结果
        [mKey.type]: this.gameMessage.WKU ? 1 : 2,
      },ip);
    }
    if(this.gameMessage.gameState === 105 && element.isLive && !element.out && element.operated === 1){
      // 发送投票技能
      this.send({[mKey.messageType]: sendKey.vote_permit},ip);
    }
    if(this.gameMessage.gameState === 106 && element.isLive && !element.out && element.operated === 1){
      // 发送重复投票技能
      this.send({
        [mKey.messageType]: sendKey.revote_permit,
        [mKey.revoteCanVote]: this.gameMessage.revoteCanVote
      },ip);
    }
  }

  // 销毁
  destroy() {
    console.log('destroy222222===========')
    this.UDP.close();
    this.UDP.offMessage();
    this.UDP = null;
    this.messageQueue = [];
    this.pendingMessages.clear();
    this.lastHeartbeats.clear(); // 客户端最后心跳时间
    clearInterval(this.heartbeat);
    this.heartbeat = null;
    this.gameMessage = JSON.parse(JSON.stringify(config.gameMessage));
    this.outsideQuery.clear();
    this.paddingMessageBack.clear();
    this.clearAudios();
    this.pageContext.setData({ Server: null });
    // 清除待发送消息
    clearTimeout(this.pollingSetTimeout);
    this.pollingSetTimeout = null;

  }

  /****************************************音频 start ****************************************************/
  // 角色以及音频准备
  // 预加载方法
  setNewAudio(path) { 
    const audio = wx.createInnerAudioContext({ useWebAudioImplement: true });
    audio.src = path;
    return audio;
  }
  // 准备工作
  async characterAudioPreparation() {
    this.clearAudios()
    this.gameStartAudio = [
      {type: 0, audioContext: this.setNewAudio('/audio/audio0.mp3')},   // 天黑了
      {type: 100, audioContext: this.setNewAudio('/audio/audio100.mp3')}, // 请闭眼
      {type: -1, audioContext: undefined}, // 延时
    ]
    this.gameEndAudio = [
      {type: 104, audioContext: this.setNewAudio('/audio/audio104.mp3')},   // 天亮了
      {type: 101, audioContext: this.setNewAudio('/audio/audio101.mp3')},  // 请睁眼
    ]
    const code = this.gameMessage.players.map((item) => item.code);
    // 狼
    if(code.includes(7)){
      this.wolfStartAudio = [
        {type: 1, audioContext: this.setNewAudio('/audio/audio1.mp3')},   // 狼人
        {type: 101, audioContext: this.setNewAudio('/audio/audio101.mp3')},  // 请睁眼
      ]
      for (let index = 0; index < this.gameMessage.wolf_time; index++) {
        this.wolfAudioTime.push({type: 102, audioContext: this.setNewAudio('/audio/audio102.mp3')}) // kakaka
      }
      this.wolfEndAudio = [
        {type: 103, audioContext: this.setNewAudio('/audio/audio103.mp3')},   // 时间到
        {type: 10, audioContext: this.setNewAudio('/audio/audio1.mp3')},   // 狼人
        {type: 100, audioContext: this.setNewAudio('/audio/audio100.mp3')},  // 请闭眼
        {type: -1, audioContext: undefined}, // 延时

      ]
    }
    // 女巫
    if(code.includes(5)){
      this.witchStartAudio = [
        {type: 2, audioContext: this.setNewAudio('/audio/audio2.mp3')},   // 女巫
        {type: 101, audioContext: this.setNewAudio('/audio/audio101.mp3')}  // 请睁眼
      ]
      for (let index = 0; index < this.gameMessage.witch_time; index++) {
        this.witchAudioTime.push({type: 102, audioContext: this.setNewAudio('/audio/audio102.mp3')}) // kakaka
      }
      this.witchEndAudio = [
        {type: 103, audioContext: this.setNewAudio('/audio/audio103.mp3')},   // 时间到
        {type: 20, audioContext: this.setNewAudio('/audio/audio2.mp3')},   // 女巫
        {type: 100, audioContext: this.setNewAudio('/audio/audio100.mp3')},  // 请闭眼
        {type: -1, audioContext: undefined}, // 延时
      ]
    }
    // 守卫
    if(code.includes(3)){
      this.guardStartAudio = [
        {type: 3, audioContext: this.setNewAudio('/audio/audio3.mp3')},   // 守卫
        {type: 101, audioContext: this.setNewAudio('/audio/audio101.mp3')}  // 请睁眼
      ]
      for (let index = 0; index < this.gameMessage.guard_time; index++) {
        this.guardAudioTime.push({type: 102, audioContext: this.setNewAudio('/audio/audio102.mp3')}) // kakaka
      }
      this.guardEndAudio = [
        {type: 103, audioContext: this.setNewAudio('/audio/audio103.mp3')},   // 时间到
        {type: 30, audioContext: this.setNewAudio('/audio/audio3.mp3')},   // 守卫
        {type: 100, audioContext: this.setNewAudio('/audio/audio100.mp3')},  // 请闭眼
        {type: -1, audioContext: undefined}, // 延时

      ]
    }
    // 预言家
    if(code.includes(4)){
      this.prophetStartAudio = [
        {type: 4, audioContext: this.setNewAudio('/audio/audio4.mp3')},   // 预言家
        {type: 101, audioContext: this.setNewAudio('/audio/audio101.mp3')}  // 请睁眼
      ]
      for (let index = 0; index < this.gameMessage.prophet_time; index++) {
        this.prophetAudioTime.push({type: 102, audioContext: this.setNewAudio('/audio/audio102.mp3')}) // kakaka
      }
      this.prophetEndAudio = [
        {type: 103, audioContext: this.setNewAudio('/audio/audio103.mp3')},   // 时间到
        {type: 40, audioContext: this.setNewAudio('/audio/audio4.mp3')},   // 预言家
        {type: 100, audioContext: this.setNewAudio('/audio/audio100.mp3')},  // 请闭眼
        {type: -1, audioContext: undefined}, // 延时
      ]
    }
    // 预加载音频
    this.preloadAudios();
  }

  // 预加载音频
  preloadAudios() {
    const listAudio = [
      ...this.gameStartAudio,
      ...this.wolfStartAudio,
      ...this.wolfAudioTime,
      ...this.wolfEndAudio,
      ...this.witchStartAudio,
      ...this.witchAudioTime,
      ...this.witchEndAudio,
      ...this.guardStartAudio,
      ...this.guardAudioTime,
      ...this.guardEndAudio,
      ...this.prophetStartAudio,
      ...this.prophetAudioTime,
      ...this.prophetEndAudio,
      ...this.gameEndAudio
    ]
    this.preloadedAudioContexts = listAudio;
  }

    // 清空音频
  clearAudios() { 
    this.destroyAudios() // 实例

    this.gameStartAudio = []  // 天黑了 请闭眼
  
    this.wolfStartAudio = [] // 狼人请睁眼
    this.wolfEndAudio = []   // 狼人请闭眼
  
    this.witchStartAudio = [] // 女巫请睁眼
    this.witchEndAudio = []   // 女巫请闭眼
  
    this.guardStartAudio = [] // 守卫请睁眼
    this.guardEndAudio = []   // 守卫请闭眼
  
    this.prophetStartAudio = [] // 预言家请睁眼
    this.prophetEndAudio = []   // 预言家请闭眼
  
    this.wolfAudioTime = []  // 狼人播放时长
    this.witchAudioTime = [] // 女巫播放时长
    this.guardAudioTime = [] // 守卫播放时长
    this.prophetAudioTime = [] // 预言家播放时长
  
    this.gameEndAudio = []  // 天亮了

    this.preloadedAudioContexts = [];

    this.isPlayingAudio = false;
    this.currentAudioIndex = 0;
  }

  // 销毁音频实例
  destroyAudios() {
    const listAudio = [
      'gameStartAudio',
      'wolfStartAudio',
      'wolfAudioTime',
      'wolfEndAudio',
      'witchStartAudio',
      'witchAudioTime',
      'witchEndAudio',
      'guardStartAudio',
      'guardAudioTime',
      'guardEndAudio',
      'prophetStartAudio',
      'prophetAudioTime',
      'prophetEndAudio',
      'gameEndAudio',
      'preloadedAudioContexts'
    ]
    listAudio.forEach((obj) => {
      // console.log('销毁音频实例', this[obj]);
      this[obj].forEach((element) => {
        try {
          if(element?.audioContext && element.audioContext?.stop){
            element.audioContext?.stop();
          }
        } catch (error) {}
        try {
          if(element?.audioContext && element.audioContext?.destroy){
            element.audioContext?.destroy();
          }
        } catch (error) {}
      });
    });
  }

  // 开始播放音频
  startAudioSequence() {
    if (this.isPlayingAudio) return;
    this.isPlayingAudio = true;
    this.currentAudioIndex = 0;
    this.playNextAudio();
  }

  // 播放下一个音频
  playNextAudio() {
    if (this.currentAudioIndex >= this.preloadedAudioContexts.length && this.currentAudioIndex !== 0 && this.preloadedAudioContexts.length !== 0) {
      // 一轮结束 开始结算
      this.operationSettlement();
      this.isPlayingAudio = false;
      return;
    }
    const audioElement = this.preloadedAudioContexts[this.currentAudioIndex];
    console.log(audioElement.type,Date.now(),'=========时间=======')
    // 延时
    if (audioElement.type === -1) {
      setTimeout(() => {
        this.currentAudioIndex++;
        this.playNextAudio();
      }, 3000);
      return;
    }
    const onPlay = () => {
      if (audioElement.type === 1) {
        // 狼
        this.wolf_send_time = Date.now()
        this.broadcastMessage({
          [mKey.messageType]: sendKey.wolf_permit,
          [mKey.version]: this.computedVersion(),
          [mKey.progressTime]: this.gameMessage.wolf_time,
          [mKey.sendTime]: this.wolf_send_time
        });
        this.setCodeOperated(7)
      } else if (audioElement.type === 2) {
        // 女巫
        this.killCountComputer();
        this.witch_send_time = Date.now()
        this.broadcastMessage({
          [mKey.messageType]: sendKey.witch_permit,
          [mKey.WKU]: this.gameMessage.WKU,
          [mKey.witchKill]: this.gameMessage.witchKill, // 是否有毒药
          [mKey.witchSave]: this.gameMessage.witchSave, // 是否有解药
          [mKey.version]: this.computedVersion(),
          [mKey.progressTime]: this.gameMessage.witch_time,
          [mKey.sendTime]: this.witch_send_time
        });
        this.setCodeOperated(5)
      } else if (audioElement.type === 3) {
        // 守卫
        this.guard_send_time = Date.now()
        this.broadcastMessage({
          [mKey.messageType]: sendKey.guard_permit,
          [mKey.version]: this.computedVersion(),
          [mKey.progressTime]: this.gameMessage.guard_time,
          [mKey.sendTime]: this.guard_send_time
        });
        this.setCodeOperated(3)

      } else if (audioElement.type === 4) {
        // 预言家
        this.prophet_send_time = Date.now()
        this.broadcastMessage({
          [mKey.messageType]: sendKey.prophet_permit,
          [mKey.progressTime]: this.gameMessage.prophet_time,
          [mKey.sendTime]: this.prophet_send_time,
          [mKey.version]: this.computedVersion()
        });
        this.setCodeOperated(4)
      } else if (audioElement.type === 0) {
        // 天黑了
        this.broadcastMessage({
          [mKey.messageType]: sendKey.ban_permit,
          [mKey.version]: this.computedVersion()
        });
        return;
      } else if (audioElement.type === 100) {
        // 请闭眼
        this.broadcastMessage({
          [mKey.messageType]: sendKey.closeEyes,
          [mKey.version]: this.computedVersion()
        });
        return;
      }
      // 100 请闭眼    101 请睁眼    102卡卡卡   103 当   104天亮了
    };
    const audioContext = audioElement.audioContext;
    const onEnded = () => {
      // 播放完毕
      this.currentAudioIndex++;
      this.playNextAudio();
      audioContext.offPlay(onPlay);
      audioContext.offEnded(onEnded);
      audioContext.offError(onError);
    };
    const onError = (err) => {
      // 播放出错 跳过
      this.currentAudioIndex++;
      this.playNextAudio();
      audioContext.offPlay(onPlay);
      audioContext.offEnded(onEnded);
      audioContext.offError(onError);
    };
    audioContext.onPlay(onPlay);
    audioContext.onEnded(onEnded);
    audioContext.onError(onError);
    audioContext.play();
  }

  /**************************************** 服务端玩家业务 ****************************************************/
  // 更新用户信息
  upDataUserInfo() {
    this.userInfo = wx.getStorageSync("userInfo");
    // 更新数据
    this.broadcastMessage({
      [mKey.messageType]: sendKey.updataUser,
      [mKey.userName]: this.userInfo.userName,
      [mKey.userPicture]: this.userInfo.userPicture,
      [mKey.userIp]: this.gameMessage.gameIp,
      [mKey.version]: this.computedVersion(),
    });
  }
    // 服务器参加游戏-杀人
  setWolfKill(element) {
    const killCountsMap = this.killCountsMap.get(element.ip);
    if (killCountsMap) {
      killCountsMap.num++;
      this.killCountsMap.set(element.ip, killCountsMap);
    } else {
      this.killCountsMap.set(element.ip, { num: 1 });
    }
    this.setPartOperated(this.gameMessage.gameIp,2)
  }
  // 服务器参加游戏-毒人
  setWitchKill(element) {
    this.gameMessage.witchKill = false;
    this.gameMessage.WIKU = element.ip;
    this.gameMessage = this.gameMessage
    this.setPartOperated(this.gameMessage.gameIp,2)
  }

  // 服务器参加游戏-救人
  setWitchSave(element) {
    this.gameMessage.witchSave = false;
    this.gameMessage.WISU = element.ip;
    this.gameMessage = this.gameMessage
    this.setPartOperated(this.gameMessage.gameIp,2)
  }

  // 服务器参加游戏-守
  setGuardPart(element) {
    this.gameMessage.witchSave = false;
    this.gameMessage.GKU = element.ip;
    this.gameMessage = this.gameMessage
    this.setPartOperated(this.gameMessage.gameIp,2)
  }

  // 服务器参加游戏-查
  setProphetPart(element) {
    this.gameMessage.PKU = element.ip;
    this.gameMessage = this.gameMessage
    this.setPartOperated(this.gameMessage.gameIp,2)
  }

  // 服务器参加游戏-猎
  setHunterPart(element) {
    this.gameMessage.HKU = element.ip;
    this.gameMessage = this.gameMessage
    this.setPartOperated(this.gameMessage.gameIp,2)
    this.hunterSettlement();
  }

  // 服务器参加游戏-投
  setVoteKill(element) {
    this.setPartOperated(this.gameMessage.gameIp,2)
    if (element) {
      const voteCountsMap = this.voteCountsMap.get(element.ip);
      if (voteCountsMap) {
        voteCountsMap.num = voteCountsMap.num + 1;
        this.voteCountsMap.set(element.ip, voteCountsMap);
      } else {
        this.voteCountsMap.set(element.ip, { ...element, num: 1 });
      }

      const gameVoteCollect = this.gameMessage.gameVoteCollect
      const gameVoteList = Object.keys(gameVoteCollect) || []
      const isExist = gameVoteList.includes(element.ip)
      if(isExist){
        if(!gameVoteCollect[element.ip].includes(this.gameMessage.gameIp)){
          gameVoteCollect[element.ip].push(this.gameMessage.gameIp)
        }
      }else{
        gameVoteCollect[element.ip] = [this.gameMessage.gameIp]
      }
      this.gameMessage.gameVoteCollect = gameVoteCollect
      this.gameMessage = this.gameMessage
    }
  }
  /**************************************** 法官业务 ****************************************************/

  // 角色分发身份
  issuePart() {
    // 判断人员是不是满了 
    const isFilled = this.gameMessage.players.find(element => !element.ip);
    if(isFilled){
      wx.showToast({
        title: "人员未满",
        icon: "none",
        mask: true,
        duration: 3000,
      });
      return;
    }
    // 判断人员是不是都在线
    const leave = this.gameMessage.players.find(element => !element.isLine);
    if(leave){
      wx.showToast({
        title: "人员离开",
        icon: "none",
        mask: true,
        duration: 3000,
      });
      return;
    }
    // 格式化女巫技能
    this.gameMessage.witchkill = true;
    this.gameMessage.witchSave = true;
    const gameMessage = JSON.parse(JSON.stringify(this.gameMessage));
    const partRole = gameMessage.players.map(m => m.code);
    for (let index = 0; index < 5; index++) {
      // 随机生成3次角色
      for (let i = partRole.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [partRole[i], partRole[j]] = [partRole[j], partRole[i]];
      }
    }
    const sendCodeList = []
    gameMessage.players.forEach((element, index) => {
      sendCodeList.push({ip: element.ip, code: partRole[index]})
    });
    this.broadcastMessage({
      [mKey.messageType]: sendKey.issuePart,
      [mKey.codeList]: partRole,
      [mKey.version]: this.computedVersion()
    })
    this.pageContext.setMainStatus(2)
  }
  // 设置时间
  setGameTime(){
    const { wolf_time, witch_time, guard_time, prophet_time} = this.gameMessage;
    if(this.wolfAudioTime.length > 0 && this.wolfAudioTime.length < wolf_time){
      for (let index = 0; index < wolf_time - this.wolfAudioTime.length; index++) {
          this.wolfAudioTime.push({type: 102, audioContext: this.setNewAudio('/audio/audio102.mp3')}) // kakaka
      }
    }
    if(this.wolfAudioTime.length > 0 && this.wolfAudioTime.length > wolf_time){
      const deleteCount = this.wolfAudioTime.length - wolf_time;
      this.wolfAudioTime.splice(-deleteCount, deleteCount)
    }
    if(this.witchAudioTime.length > 0 && this.witchAudioTime.length < witch_time){
      for (let index = 0; index < witch_time - this.witchAudioTime.length; index++) {
          this.witchAudioTime.push({type: 102, audioContext: this.setNewAudio('/audio/audio102.mp3')}) // kakaka
      }
    }
    if(this.witchAudioTime.length > 0 && this.witchAudioTime.length > witch_time){
      const deleteCount = this.witchAudioTime.length - witch_time;
      this.witchAudioTime.splice(-deleteCount, deleteCount)
    }
    if(this.guardAudioTime.length > 0 && this.guardAudioTime.length < guard_time){
      for (let index = 0; index < guard_time - this.guardAudioTime.length; index++) {
          this.guardAudioTime.push({type: 102, audioContext: this.setNewAudio('/audio/audio102.mp3')}) // kakaka
      }
    }
    if(this.guardAudioTime.length > 0 && this.guardAudioTime.length > guard_time){
      const deleteCount = this.guardAudioTime.length - guard_time;
      this.guardAudioTime.splice(-deleteCount, deleteCount)
    }
    if(this.prophetAudioTime.length > 0 && this.prophetAudioTime.length < prophet_time){
      for (let index = 0; index < prophet_time - this.prophetAudioTime.length; index++) {
          this.prophetAudioTime.push({type: 102, audioContext: this.setNewAudio('/audio/audio102.mp3')}) // kakaka
      }
    }
    if(this.prophetAudioTime.length > 0 && this.prophetAudioTime.length > prophet_time){
      const deleteCount = this.prophetAudioTime.length - prophet_time;
      this.prophetAudioTime.splice(-deleteCount, deleteCount)
    }
    // 预加载音频
    this.preloadAudios();
  }



  // 点击进入黑夜
  startGame() {
    this.killCountsMap.clear(); // 狼人杀人
    this.gameMessage.WKU = undefined; // 狼人杀人 最终被杀那个人
    this.gameMessage.GKU = undefined; // 守卫保护的
    this.gameMessage.PKU = undefined; // 预言家查看的人
    this.gameMessage.WIKU = undefined; // 毒药的杀人
    this.gameMessage.WISU = undefined; // 解药的救人
    this.gameMessage.HKU = undefined; // 猎人带人
    this.gameMessage.knockOut = []; // 淘汰的人
    this.gameMessage.gameVoteCollect = {}; // 投票结果
    this.gameMessage = this.gameMessage
    this.voteCountsMap.clear(); // 投票数
    this.pageContext.setData({btnStatus:0})
    // 发送的时间
    this.wolf_send_time = null
    this.witch_send_time = null
    this.guard_send_time = null
    this.prophet_send_time = null
    // 开始播放
    this.startAudioSequence();
  }

  // 开始投票
  startVote() {
    this.gameMessage.gameVoteCollect = {}; // 投票结果
    this.gameMessage = this.gameMessage
    this.broadcastMessage({
      [mKey.messageType]: sendKey.vote_permit,
      [mKey.version]: this.computedVersion(),
    });
    this.pageContext.setMainStatus(4)
  }

  // 投票统计
  endVote() {
    this.voteSettlement();
  }

  // 再来一局
  resetPart() {
    this.broadcastMessage({
      [mKey.messageType]: sendKey.reset_permit,
      [mKey.version]: this.computedVersion(),
    });
    this.pageContext.setMainStatus(1)
    if(!this.preloadedAudioContexts.length){
      // 同步角色和数量
      this.setRoleAndCount()
      // 角色以及音频准备
      this.characterAudioPreparation();
    }
  }


  // 整理狼杀结果
  killCountComputer() {
    let maxNum = 0;
    let maxIP = undefined;
    for (const [ip, { num }] of this.killCountsMap) {
      if (num > maxNum) {
        maxNum = num;
        maxIP = ip;
      }
    }
    this.gameMessage.WKU = maxIP;
    this.gameMessage = this.gameMessage
  }

  // 操作结算
  operationSettlement() {
    this.killCountComputer();
    // 狼和守卫 选择相同的人 
    if (this.gameMessage.WKU === this.gameMessage.GKU) this.gameMessage.WKU = undefined;
    // 狼和解药 选择相同的人 
    if (this.gameMessage.WKU === this.gameMessage.WISU) this.gameMessage.WKU = undefined;
    // 狼和毒药药 选择相同的人
    if (this.gameMessage.WKU === this.gameMessage.WIKU) this.gameMessage.WKU = undefined;
    this.gameMessage = this.gameMessage;
    const knockOut = [this.gameMessage.WKU, this.gameMessage.WIKU].filter((d) => d);
    // 设置活着的人 可以操作
    this.livePermitOperated()
    // 平安夜
    if (knockOut.length === 0) {
       this.gameMessage = this.gameMessage
       this.broadcastMessage({
         [mKey.messageType]: sendKey.safety,
         [mKey.version]: this.computedVersion(),
       });
      this.gameMessage = this.gameMessage
      this.pageContext.setMainStatus(3)
       return;
    }
    // 结算
    const state = this.getOverState(knockOut);
    if (state === 0 || state === 3) {
      // 狼杀猎人----告诉猎人和其他人
      const { element:outElement } = this.getAssignPart(this.gameMessage.WKU);
      if (outElement && outElement.code === 2) {
        this.broadcastMessage({
          [mKey.messageType]: sendKey.hunter_permit,
          [mKey.knockOut]: knockOut,
          [mKey.gameVoteCollect]: {},
          [mKey.type]: 1,
        });
        return;
      }
      // 正常结算
      this.broadcastMessage({
        [mKey.messageType]: sendKey.knockOut,
        [mKey.knockOut]: knockOut,
        [mKey.version]: this.computedVersion(),
      });
      this.pageContext.setMainStatus(3)
    }
    if (state === 1) {
      // `好人胜利`
      this.broadcastMessage({
        [mKey.messageType]: sendKey.server_good_win,
        [mKey.version]: this.computedVersion(),
        [mKey.type]: 1,
        [mKey.knockOut]: knockOut,
      });
      this.pageContext.setMainStatus(5)
    }
    if (state === 2) {
      // `狼人胜利`
      this.broadcastMessage({
        [mKey.messageType]: sendKey.server_wolf_win,
        [mKey.type]: 1,
        [mKey.version]: this.computedVersion(),
        [mKey.knockOut]: knockOut,
      });
      this.pageContext.setMainStatus(5)
    }
    this.gameMessage = this.gameMessage
  }

  // 投票结算
  voteSettlement() {
    // 无人被投出
    if(this.voteCountsMap.size === 0){
      const state = this.getOverState();
      // `狼人胜利`
      if (state === 2 || state === 3) {
        this.broadcastMessage({
          [mKey.messageType]: sendKey.server_wolf_win,
          [mKey.version]: this.computedVersion(),
          [mKey.type]: 2,
          [mKey.knockOut]: []
        });
        this.pageContext.setMainStatus(5)
      }else{
        // 继续游戏
        this.broadcastMessage({
          [mKey.messageType]: sendKey.noVote,
          [mKey.version]: this.computedVersion()
        });
        this.pageContext.setMainStatus(2)
      }
    }
    // 多人被投出
    if(this.voteCountsMap.size > 0){
      let maxValue = 0;
      const maxNumberArr = [];
      for (const [ip, { num }] of this.voteCountsMap) {
        if (num > maxValue) {
          maxValue = num;
        }
      }
      for (const [ip, element] of this.voteCountsMap) {
        if (element.num === maxValue) {
          maxNumberArr.push(ip);
        }
      }
      // 只有1人
      if(maxNumberArr.length === 1){
        const outElement = this.getAssignPart(maxNumberArr[0])?.element || {};
        // 淘汰的是猎人----告诉猎人和其他人
        if (outElement.code === 2) {
          this.broadcastMessage({
            [mKey.messageType]: sendKey.hunter_permit,
            [mKey.knockOut]: [outElement.ip],
            [mKey.gameVoteCollect]: this.gameMessage.gameVoteCollect, // 投票结果
            [mKey.type]: 2,
          });
          return;
        }
        // 淘汰的是否是白痴
        const state = outElement.code === 6 ? this.getOverState() : this.getOverState([outElement.ip]);
        // 继续游戏
        if (state === 0) {
          this.broadcastMessage({
            [mKey.messageType]: sendKey.voteEnd,
            [mKey.userIp]: outElement.ip,
            [mKey.gameVoteCollect]: this.gameMessage.gameVoteCollect, // 投票结果
            [mKey.version]: this.computedVersion()
          });
          this.pageContext.setMainStatus(2)
        }
        // 好人胜利
        if (state === 1) {
          this.broadcastMessage({
            [mKey.messageType]: sendKey.server_good_win,
            [mKey.version]: this.computedVersion(),
            [mKey.type]: 2,
            [mKey.gameVoteCollect]: this.gameMessage.gameVoteCollect, // 投票结果
            [mKey.knockOut]: [outElement.ip]
          });
          this.pageContext.setMainStatus(5)
        }
        // `狼人胜利`
        if (state === 2 || state === 3) {
          this.broadcastMessage({
            [mKey.messageType]: sendKey.server_wolf_win,
            [mKey.version]: this.computedVersion(),
            [mKey.type]: 2,
            [mKey.gameVoteCollect]: this.gameMessage.gameVoteCollect, // 投票结果
            [mKey.knockOut]: [outElement.ip]
          });
          this.pageContext.setMainStatus(5)
        }
        this.gameMessage = this.gameMessage
      }
      // 多人 pk
      if(maxNumberArr.length > 1){
        this.livePermitOperated()
        this.gameMessage.revoteCanVote = maxNumberArr
        this.gameMessage.gameVoteCollect = {}
        this.gameMessage = this.gameMessage
        this.broadcastMessage({
          [mKey.messageType]: sendKey.revote_permit,
          [mKey.revoteCanVote]: maxNumberArr,
          [mKey.version]: this.computedVersion()
        });
        this.pageContext.setMainStatus(4)
        this.voteCountsMap.clear();
      }
    }
  }
  // 猎人携带后结算
  hunterSettlement(){
    this.gameMessage.HKU && this.setPartOffLive(this.gameMessage.HKU);
    const state = this.getOverState([this.gameMessage.HKU]);
    // 继续游戏
    if (state === 0) {
      this.broadcastMessage({
        [mKey.messageType]: sendKey.hunter_kill_end,
        [mKey.userIp]: this.gameMessage.HKU,
        [mKey.version]: this.computedVersion()
      });
      if (this.gameMessage.WKU) {
        // 狼杀的猎
        this.pageContext.setMainStatus(3)
      } else {
        // 投票的猎
        this.pageContext.setMainStatus(2)
      }
    }
    // 好人胜利
    if (state === 1) {
      this.broadcastMessage({
        [mKey.messageType]: sendKey.server_good_win,
        [mKey.version]: this.computedVersion(),
        [mKey.type]: 3,
        [mKey.HKU]: this.gameMessage.HKU,
        [mKey.knockOut]: [...this.gameMessage.knockOut,this.gameMessage.HKU]
      });
      this.pageContext.setMainStatus(5)
    }
    // `狼人胜利`
    if (state === 2 || state === 3) {
      this.broadcastMessage({
        [mKey.messageType]: sendKey.server_wolf_win,
        [mKey.type]: 3,
        [mKey.version]: this.computedVersion(),
        [mKey.HKU]: this.gameMessage.HKU,
        [mKey.knockOut]: [...this.gameMessage.knockOut,this.gameMessage.HKU]
      });
      this.pageContext.setMainStatus(5)
    }
  }
  // 猎人放弃后结算
  hunterGiveUpSettlement(){
    const state = this.getOverState();
    // 继续游戏
    if (state === 0) {
      this.broadcastMessage({
        [mKey.messageType]: sendKey.hunter_giveUp,
        [mKey.version]: this.computedVersion(),
        [mKey.knockOut]: this.gameMessage.knockOut,
      });
      if (this.gameMessage.WKU) {
        // 狼杀的猎
        this.pageContext.setMainStatus(3)
      } else {
        // 投票的猎
        this.pageContext.setMainStatus(2)
      }
    }
    // 好人胜利
    if (state === 1) {
      this.broadcastMessage({
        [mKey.messageType]: sendKey.server_good_win,
        [mKey.version]: this.computedVersion(),
        [mKey.type]: 3,
        [mKey.knockOut]: this.gameMessage.knockOut,
      });
      this.pageContext.setMainStatus(5)
    }
    // `狼人胜利`
    if (state === 2 || state === 3) {
      this.broadcastMessage({
        [mKey.messageType]: sendKey.server_wolf_win,
        [mKey.type]: 3,
        [mKey.version]: this.computedVersion(),
        [mKey.knockOut]: this.gameMessage.knockOut,
      });
      this.pageContext.setMainStatus(5)
    }
  }
}
